local Args = {...}

local run = true
local xSize, ySize = term.getSize()
local xCenter = math.floor(xSize/2)
local yCenter = math.floor(ySize/2)
local obj = {}
local path = "/"
local files = {}
local pos = 0
local prevPath = {}
prevPath[0] = "/"
local history = 0
local lenthScroll = 0
local posScroll = 0
local step = 0
local lenthPage = 0
local select = 0
local selects = {}
local sel = false
local contex = false
local corpath = ""
local screen = window.create(term.native(),1,3,xSize-1,ySize-3)
local draw = true
local ender = 0

local function init()
	icoFld = '/System/folder.png'
	icoApp = "/System/app.png"
	icoProg = "/System/prog.png"
	icoPic = "/System/picture.png"
	icoTxt = "/System/text.png"
	icoZip = "/System/archive.png"
	icoRom = "/System/rom.png"
	icoUnk = "/System/unknown.png"
	header = "File Manager"
	os.loadAPI("/System/API/image")
	os.loadAPI("/System/API/sysbar")
	os.loadAPI("/System/API/zip")
	os.loadAPI("/System/API/contexts")
end

local newObj = function(name,x1,y1,x2,y2)
 obj[name] = {}
 obj[name]["x1"] = x1
 obj[name]["y1"] = y1
 obj[name]["x2"] = x2
 obj[name]["y2"] = y2
end

local clear = function(color)
 term.setBackgroundColor(color)
 term.clear()
 term.setCursorPos(1,1)
end

if version < '5.1.1' then
 clear(colors.white)
 windows.error('Update your OS')
 run = false
else
 --os.loadAPI("/System/API/contexts")
end

local text = function(string,xPos,yPos)
 term.setCursorPos(xPos,yPos)
 term.write(string)
end

local fadeIn = function()
 for i=1,xSize do
  paintutils.drawLine(i,1,i,ySize-1,colors.black)
  sleep(0)
 end
end

if not(icoFld) then
	init()
end

local function fadeOut(time)
        clear(colors.lightGray)
        sleep(time)
        clear(colors.gray)
        sleep(time)
        clear(colors.black)
        sleep(time)
        term.setCursorPos(1,1)
        term.setTextColor(colors.black)
end

local sysBar = function()
	step = sysbar.scrollBar(#files,4,posScroll,2)
	sysbar.header(header,mainTextCol,mainColor)
	if #path>xSize then
		text(path,xSize-#path+1,2)
		text("...",2,2)
	else
		text(path,1,2)
	end
	if #path > 1 then
		text("^",1,2)
	end
	paintutils.drawLine(1,ySize,xSize,ySize,colors.white)
	term.setTextColor(colors.black)
	if select==0 then
		newObj("()",0,0,0,0)
		newObj("<<",0,0,0,0)
		sysbar.draw(colors.white,colors.black,noty,true,true)
	else
		if select==1 then
			text(" Copy",1,ySize)
			text(" Cut",6,ySize)
			text(" Delete",10,ySize)
			if #selects~=#files then
				text(" All ",xSize-5,ySize)
			else
				text(" One ",xSize-5,ySize)
			end
			newObj("()",xSize-6,ySize,xSize-1,ySize)
			newObj("<<",xSize,ySize,xSize,ySize)
		elseif select>1 then
			text(" Paste",1,ySize)
			text(" Cancel ",7,ySize)
		end
		term.setTextColor(colors.red)
		text("x",xSize,ySize)
	end
end

local function timer()
	local time = ''
	while true do
		if draw and select==0 and xSize > 30 then
			paintutils.drawLine(xSize-6,ySize,xSize-2,ySize,colors.white)
			term.redirect(term.native())
			term.setTextColor(colors.black)
			time = textutils.formatTime(os.time(),true)
			text(time,xSize-#time-1,ySize)
		end
		sleep(1)
	end
end

local delik = function(y,color)
 for i=2,xSize-2 do
  term.setBackgroundColor(colors.wite)
  term.setTextColor(color)
  text("-",i,y)
 end
end

local redraw = function()
	if version >= '5.1.1' then
		term.redirect(screen)
		clear(colors.white)
		files = fs.list(path)
		files = windows.reorganizeFilesAndFolders(path,files,true,true)
		ender = math.floor((-pos)/4+ySize/4)
		if ender > #files then
			ender = #files
		end
		for I=math.floor((-pos)/4)+1,ender do
			yPos = pos+4*I-2
			if fs.isDir(path.."/"..files[I]) and windows.getFileFormat(files[I]) ~= ".apk" then
				image.draw(2,yPos,icoFld)
			elseif (windows.getFileFormat(files[I])==".apk" or windows.getFileFormat(files[I])==".app") then
				image.draw(2,yPos,icoApp)
			elseif not fs.isDir(path.."/"..files[I]) then
				if (windows.getFileFormat(files[I]) == nil or windows.getFileFormat(files[I])=='.lua' or windows.getFileFormat(files[I])=='.exe')then
					image.draw(2,yPos,icoProg)
				elseif (windows.getFileFormat(files[I])==".png" or windows.getFileFormat(files[I])==".pic" or windows.getFileFormat(files[I])==".jpg" or windows.getFileFormat(files[I])==".skch" or windows.getFileFormat(files[I])==".nft" or windows.getFileFormat(files[I])==".nfp") then
					image.draw(2,yPos,icoPic)
				elseif (windows.getFileFormat(files[I])==".txt" or windows.getFileFormat(files[I])==".cfg" or windows.getFileFormat(files[I])==".ini" or windows.getFileFormat(files[I])==".md") then
					image.draw(2,yPos,icoTxt)
				elseif (windows.getFileFormat(files[I])==".zip" or windows.getFileFormat(files[I])==".rar" or windows.getFileFormat(files[I])==".7z" or windows.getFileFormat(files[I])==".tar" or windows.getFileFormat(files[I])==".gz") then
					image.draw(2,yPos,icoZip)
				elseif (windows.getFileFormat(files[I])==".rom" or windows.getFileFormat(files[I])==".img" or windows.getFileFormat(files[I])==".iso" or windows.getFileFormat(files[I])==".back") then
					image.draw(2,yPos,icoRom)
				else
					image.draw(2,yPos,icoUnk)
				end
				term.setBackgroundColor(colors.white)
				term.setTextColor(colors.lightGray)
				if fs.getSize(path..'/'..files[I]) >= 1024 then
					text(math.floor(fs.getSize(path..'/'..files[I])/1024).." KB",7,yPos+2)
				else
					text(fs.getSize(path..'/'..files[I]).." B",7,yPos+2)
				end
			end
			term.setBackgroundColor(colors.white)
			term.setTextColor(colors.black)
			text(files[I],7,yPos+1)
			newObj(files[I],2,yPos,xSize,yPos+2)
			if select == 1 then
				term.setTextColor(colors.lightGray)
				text("[ ]",xSize-4,yPos+1)
				for ii=1,#selects do
					if selects[ii]==files[I] then
						term.setTextColor(mainSwitchCol)
						text("V",xSize-3,yPos+1)
					end
				end
			end
		end
		term.redirect(term.native())
		sysBar()
	end
end

local waitKey = function()
	local wait = true
	while wait do
		eve = os.pullEvent()
		if eve == 'mouse_click' or eve == 'key' then
			wait = false
		end
	end
end

local running = function()
 while run == true and home == false do
  event, side, x, y = os.pullEvent()
  if event == "mouse_click" then
   if side == 1 then
    draw = false
	files = windows.reorganizeFilesAndFolders(path,files,true,true)
    for I=math.floor((-pos)/4)+1,ender do
     if x>=obj[files[I]]["x1"] and x<=obj[files[I]]["x2"]-1 and y>=obj[files[I]]["y1"]+2 and y<=obj[files[I]]["y2"]+2 and y<ySize then
      if select > 1 or select==0 then
       if fs.isDir(path.."/"..files[I]) then
        history = history + 1
        path = path.."/"..files[I]
        prevPath[history] = path
        pos = 0
        posScroll = 0
       elseif fs.isDir(path.."/"..files[I])==false and (windows.getFileFormat(files[I])==nil or windows.getFileFormat(files[I])=='.lua' or windows.getFileFormat(files[I])=='.exe') then
        term.setCursorPos(0,0)
        local error = os.run(os.getEnv(),path.."/"..files[I])
		if error then
			windows.error(error)
		end
       elseif fs.isDir(path.."/"..files[I])==false and windows.getFileFormat(files[I])==".sec" then
        os.run(os.getEnv(),"/ver")
        os.run(os.getEnv(),path.."/"..files[I])
       elseif fs.isDir(path.."/"..files[I])==false and (windows.getFileFormat(files[I])==".png" or windows.getFileFormat(files[I])==".pic" or windows.getFileFormat(files[I])==".jpg") then
        select=2
		if Args[1] == nil then
			os.run(os.getEnv(),"/.ds/"..l_login.."/ImageViewer.apk/main",path,files[I])
		else
			os.run({},shell.dir().."/Resources/imgView",path,files[I])
		end
		select=0
	   elseif fs.isDir(path.."/"..files[I])==false and (windows.getFileFormat(files[I])==".txt" or windows.getFileFormat(files[I])==".cfg" or windows.getFileFormat(files[I])==".ini" or windows.getFileFormat(files[I])==".md") then
	    draw = true
		if Args[1] == nil then
			os.run(os.getEnv(),"/.ds/"..l_login.."/FileBrowser.apk/Resources/reader",path.."/"..files[I])
		else
			os.run({},shell.dir().."/Resources/reader",path.."/"..files[I])
		end
       end
      else
       for ii=1,#selects do
        if files[I]==selects[ii] then
         sel=false
         for iii=ii,#selects do
          selects[iii]=selects[iii+1]
         end
        end
       end
       if sel==true then
        selects[#selects+1]=files[I]
       elseif sel==false then
        sel=true
       end
      end
      redraw()
      sel=true
      break
     end
	end
	draw = true
   elseif side == 2 then
	if select == 0 then
     files = windows.reorganizeFilesAndFolders(path,files,true,true)
     for I=math.floor((-pos)/4)+1,ender do
      if x>=obj[files[I]]["x1"] and x<=obj[files[I]]["x2"]-1 and y>=obj[files[I]]["y1"]+2 and y<=obj[files[I]]["y2"]+2 and y<ySize then
	   local budka = ""
	   if fs.isDir(path.."/"..files[I])==false and windows.getFileFormat(path.."/"..files[I])==".zip" then
	    budka = contexts.main(x,y,'Unarchive','Rename','Open as','Edit','Copy','Cut','Delete')
	   elseif fs.isDir(path.."/"..files[I])==false then
	    budka = contexts.main(x,y,'Open as','Rename','Edit','Copy','Cut','Delete')
	   else
	    budka = contexts.main(x,y,'Archive','Rename','Copy','Cut','Delete')
	   end
        if budka == 'Open as' then
		 redraw()
		 local open = windows.select({"Open "..files[I]},{"Open as"},{"x",colors.white,colors.red},{"Text",colors.lightBlue,colors.white},{"Program",colors.lightBlue,colors.white})
		 if open == 'Text' then
		  draw = true
		  local error = ""
		  if Args[1] == nil then
			error = os.run(os.getEnv(),"/.ds/"..l_login.."/FileBrowser.apk/Resources/reader",path.."/"..files[I])
		  else
			error = os.run({},shell.dir().."/Resources/reader",path.."/"..files[I])
		  end
		  if error then
			windows.error(error)
		  end
		 elseif open == 'Program' then
          term.setCursorPos(0,0)
          local error = os.run(os.getEnv(),path.."/"..files[I])
		  if error then
			windows.error(error)
		  end
		 elseif open == 'Image' then
		  select=2
		  if Args[1] == nil then
			os.run(os.getEnv(),"/.ds/"..l_login.."/ImageViewer.apk/main",path,files[I])
		  else
			os.run({},shell.dir().."/Resources/imgView",path,files[I])
		  end
		  select=0
		 end
		elseif budka == 'Unarchive' then
		 redraw()
		 local unzipPath = windows.input('auto','auto','Unarchive',20,{'Path', ''})
		 if unzipPath[1] ~= '' then
		  fs.makeDir(unzipPath[1])
		  zip.unarchive(path..'/'..files[I],unzipPath[1])
		 elseif unzipPath[1] == '' then
		  zip.unarchive(path..'/'..files[I],path)
		 end
		 redraw()
		elseif budka == 'Archive' then
		 redraw()
		 local zipName = windows.input('auto','auto','Archive',20,{'Name', ''})
		 if zipName[1] ~= '' then
		  zip.archive(path..'/'..files[I],path..'/'..zipName[1])
		 elseif zipName[1] == '' then
		  zip.archive(path..'/'..files[I],path..'/'..files[I])
		 end
		 redraw()
		elseif budka == 'Rename' then
		 redraw()
		 local newName = windows.input('auto','auto','Rename',20,{'New name', files[I]})
		 if newName[1] ~= '' then
		  shell.run('rename '..path..'/'..files[I]..' '..path..'/'..newName[1])
		 end
		 redraw()
		elseif budka == 'Edit' then
		 shell.run("edit "..path.."/"..files[I])
		elseif budka == 'Copy' then
		 select=2
		 selects[1] = files[I]
         corpath = path
         redraw()
		elseif budka == 'Cut' then
		 select=3
		 selects[1] = files[I]
         corpath = path
         redraw()
		elseif budka == 'Delete' then
		 redraw()
		 local but2 = windows.select({"Delete files"},{"Are you sure?"},{"Yes",colors.red,colors.white},{"No",colors.gray,colors.white})
     if but2 == "Yes" then
		  fs.delete(path.."/"..files[I])
		 end
		end
       redraw()
       break
      end
	 end
	end
   end
   if x==1 and y==2 then
    pos = 0
    posScroll = 0
    history=history-1
    if history<0 then history=0 end
    path = prevPath[history]
    redraw()
   elseif x==xSize and y==ySize and select==0 then
     term.setBackgroundColor(colors.gray)
     term.setTextColor(colors.lightGray)
     text("|",xSize,ySize)
	 local budka = contexts.main(xSize,ySize-1,'Select','New Folder','New File')
     if budka == 'Select' then
	  select = 1
      selects = {}
      contex = false
	 elseif budka == 'New Folder' then
	  redraw()
      newDir = windows.input("auto","auto","New Folder",14,{"Folder name",""})
      fs.makeDir(path.."/"..newDir[1])
      contex = false
	 elseif budka == 'New File' then
	  redraw()
      newFile = windows.input("auto","auto","New File",14,{"File name",""})
      shell.run("edit "..path.."/"..newFile[1])
      contex = false
	 end
	 redraw()
   elseif select == 0 and sysbar.back(x,y) then
    term.redirect(term.native())
    pos = 0
    posScroll = 0
    history=history-1
    if history<0 then history=0 end
    path = prevPath[history]
    redraw()
   elseif select == 0 and sysbar.home(x,y) then
    clear(colors.black)
	term.redirect(term.native())
    term.clear()
    term.setCursorPos(1,1)
    run = false
   elseif x>=obj["<<"]["x1"] and x<=obj["<<"]["x2"] and y>=obj["<<"]["y1"] and y<=obj["<<"]["y2"] and select == 1 then
    pos = 0
    posScroll = 0
    select=0
    selects={}
    redraw()
   elseif x>=obj["()"]["x1"] and x<=obj["()"]["x2"] and y>=obj["()"]["y1"] and y<=obj["()"]["y2"] and select == 1 then
    if #selects~=#files then
     for I=1,#files do
      selects[I]=files[I]
     end
     redraw()
    else
     selects={}
     redraw()
    end
   elseif x>9 and x<=17 and y==ySize and select==1 then
    select=0
	local but = windows.select({"Delete files"},{"Are you sure?"},{"Yes",colors.red,colors.white},{"No",colors.gray,colors.white})
     if but == "Yes" then
      for I=1,#selects do
       fs.delete(path.."/"..selects[I])
      end
	 end
    selects={}
    redraw()
   elseif x>7 and x<=15 and y==ySize and select>1 then
    select=0
    selects={}
    redraw()
   elseif x>1 and x<=7 and y==ySize and select>1 then
    local f = fs.list(path)
    for I=1,#selects do
	 local find = false
	 for i=math.floor((-pos)/4)+1,ender do
		if f[i]==selects[I] then find = true end
	 end
	 if find then
	  local check = windows.select({selects[I]},{'already exist'},{'Skip',colors.lightBlue,colors.white},{'Overwrite',colors.lightBlue,colors.white},{'Rename',colors.lightBlue,colors.white})
	  if check == 'Rename' then
	   fs.copy(corpath.."/"..selects[I],path.."/copy-"..selects[I])
	   if select==3 then
        fs.delete(corpath.."/"..selects[I])
       end
	  elseif check == 'Overwrite' then
	   fs.delete(path.."/"..selects[I])
	   fs.copy(corpath.."/"..selects[I],path.."/"..selects[I])
	  end
	 else
	  fs.copy(corpath.."/"..selects[I],path.."/"..selects[I])
	  if select==3 then
       fs.delete(corpath.."/"..selects[I])
      end
	 end
    end
    selects={}
    select=0
    redraw()
   elseif x>0 and x<=5 and y==ySize and select>0 and #selects>0 then
    select=2
    corpath = path
    redraw()
   elseif x>5 and x<=10 and y==ySize and select>0 and #selects>0 then
    select=3
    corpath = path
    redraw()
   end
  elseif event == "mouse_scroll" and contex==false then
   if #files>4 then
    if side == 1 then
     if pos>-#files*4+ySize-4 then
      posScroll = posScroll-step
      pos = pos-2
     else
      pos = -#files*4+ySize-4
     end
    elseif side == -1 then
     if pos < 0 then
      pos = pos + 2
      posScroll = posScroll+step
      if pos > 0 then
		pos = 0
	  end
     end
    end
    redraw()
   end
  elseif event == "key" then
   if side == 208 then
    if pos>-#files*4+15 then
     posScroll = posScroll-step
     pos = pos-2
    else
     pos = -#files*4+15
    end
   elseif side == 200 then
    if pos<0 then
     pos = pos+2
     posScroll = posScroll+step
    else
     pos = 0
    end
   end
   redraw()
  end
  term.redirect(term.native())
 end
end

clear(colors.white)
redraw()
parallel.waitForAny(running,timer)
icoFld = nil
icoApp = nil
icoProg = nil
icoPic = nil
icoTxt = nil
icoZip = nil
icoRom = nil
icoUnk = nil
header = nil
fadeOut(0)